package org.apache.commons.graph.bean


open class DefaultEdge<V>(
    override val source: V,
    override val target: V
) : Edge<V> {
    private var _reverse: Edge<V>? = null

    override fun toString(): String {
        return "$source->$target"
    }

    private inner class ReversedEdge : Edge<V> {
        override val source: V get() = this@DefaultEdge.target
        override val target: V get() = this@DefaultEdge.source


        override fun reverse(): Edge<V> {
            return this@DefaultEdge
        }

        override fun toString(): String {
            return "$source->$target"
        }
    }

    override fun reverse(): Edge<V> {
        if (_reverse == null) _reverse = ReversedEdge()
        return _reverse!!
    }

    fun cloneInstance(): Edge<V> {
        return this
    }

    override fun hashCode(): Int {
        return source.hashCode() * 31 + target.hashCode()
    }

    companion object {
        fun <V> of(source: V, target: V): DefaultEdge<V> {
            return DefaultEdge<V>(source, target)
        }

        fun <V> factory(): EdgeFactory<V, DefaultEdge<V>> {
            return EdgeFactory { source: V, target: V -> DefaultEdge(source, target) }
        }
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other == null || this::class != other::class) return false

        other as DefaultEdge<*>

        if (source != other.source) return false
        if (target != other.target) return false
        if (_reverse != other._reverse) return false

        return true
    }
}